"""\
R.R. Nederhoed (rr@nederhoed.com)
2007-06-24


TODO: extract XML conversion from API calls (2007-07-03)

$Id: $
"""
__version__ = "$Revision: $"

# py 2.5+
from elementtree import ElementTree as ET

import urllib
import urllib2

# Local imports
from model import WrtsList, wrtslist2xml
from model import ExamResult

class WrtsConnection(object):
    """Connection with authentication """
    _api_url = "http://www.wrts.nl/api/"
    _user_agent = 'pywrts/1.0'
    
    def __init__(self, username, password):
        """Complex authentication code """
        # Password manager
        manager = urllib2.HTTPPasswordMgrWithDefaultRealm()
        manager.add_password(None, WrtsConnection._api_url, username, password)
        # Authentication handler
        handler = urllib2.HTTPBasicAuthHandler(manager)
        # Build URL opener
        opener = urllib2.build_opener(handler)
        opener.addheaders = [('User-agent', WrtsConnection._user_agent)]
        # Set opener as default for urllib2.urlopen
        urllib2.install_opener(opener)
    
    def request(self, path, data=None):
        """Make a request to the API
        
        'path' is the url path after the API url, `lists` for example
        
        `data` is a dictionary with request data. it will be submitted 
        using 'POST'
        """
        # make request
        url = "%s%s" % (WrtsConnection._api_url, path)
        request = urllib2.Request(url)
        if data is not None:
            try:
                request.add_data(urllib.urlencode(data))
            except:
                # TODO: error handling?
                #raise ValueError('data ...')
                raise
        # Retrieve data
        return urllib2.urlopen(request).read()

class WrtsApi(object):
    """Use wrts.nl functionality from Python
    
    """
    
    def __init__(self, username, password):
        """Constructor """
        self._connection = WrtsConnection(username, password)
    
    def get_list_ids(self):
        """Request the list with IDs of wrts lists owned by the user """
        data = self._connection.request('lists')
        return [int(item.findtext('id')) for item in ET.XML(data)]
    
    def get_list(self, list_id):
        """Get the WrtsList with the given `list_id` """
        data = self._connection.request('lists/%d' % list_id)
        element = ET.XML(data)
        result = WrtsList(element.findtext('title'), list_id)
        # Words
        for combi in element.findall('words/word'):
            result.add_word_translation(combi.findtext('word-a'),
                                        combi.findtext('word-b'))
        # Keywords / tags
        result.keywords = [item.text
                           for item in element.find('keywords').findall('keyword')]
        return result
    
    def get_list_results(self, list_id):
        """Retrieve all exam results of the user for list with given list_id """
        data = self._connection.request('lists/%d/results' % list_id)
        result = []
        for element in ET.XML(data).findall('result'):
            result.append(ExamResult(list_id))
            # TODO: smarter xml to object conversion
            result[-1].created = element.findtext('created-on')
            result[-1].score = float(element.findtext('score').replace(',', '.'))
            result[-1].test_method = element.findtext('test-method')
            result[-1].seconds = int(element.findtext('seconds'))
            result[-1].test_order = element.findtext('test-order')
        return result
    
    def save_list(self, list_):
        """Store the wrts list instance on wrts.nl """
        # Convert to XML
        data = wrtslist2xml(list_)
        # POST data
        # TODO: complete methode please :)
    
    def delete_list(self, list_id):
        """Will remove all list data from wrts.nl """
        data = self._connection.request('lists/%d/delete' % list_id)
        # TODO: check success, raise error on failure
        #element = ET.XML(data)

